﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.XLANGs.BaseTypes;
using System.Diagnostics;
using Software41.Tracking.Tracing;

namespace Software41.Tracking.BAM
{
    [Serializable]
    public class ProcessTraceInfo : InfoBase
    {
        //internal const string PROCESSINFO_ACTIVITY = "ProcessInfo";
        //internal const string PROCESSINFO_ACTIVITY_NAME = "Name";
        //internal const string PROCESSINFO_ACTIVITY_BEGIN = "Begin";
        //internal const string PROCESSINFO_ACTIVITY_END = "End";
        internal const string PROCESSINFO_DATA_APPLICATION = "Application";
        internal const string PROCESSINFO_DATA_USER_ID = "UserId";
        internal const string PROCESSINFO_DATA_USER_NAME = "UserName";
        //internal const string PROCESSINFO_ACTIVITY_DATA = "ProcessInfoData";
        //internal const string PROCESSINFO_ACTIVITY_DATA_BEGIN_DATA = "BeginData";
        //internal const string PROCESSINFO_ACTIVITY_DATA_END_DATA = "EndData";

        //public ActivityStateType State { get; private set; }
        public string ProcessInfoId { get { return this.InfoId; } }

        public ProcessTraceInfo(string name, string processInfoId, IEventStream eventStream)
        {
            this.Name = name;
            this.InfoId = processInfoId;
            this.EventStream = eventStream;
            this.CurrentActivityType = ActivityType.ProcessTraceInfo;
        }

        public ProcessTraceInfo(string name, string processInfoId) :
            this(name, processInfoId, new Adapters.OrchestrationEventStreamAdapter())
        {
        }

        /// <summary>
        /// This method should ONLY be used when you are restarting a process to Update or End the activity
        /// </summary>
        /// <param name="processInfoId"></param>
        /// <param name="eventStream"></param>
        public ProcessTraceInfo(string processInfoId, IEventStream eventStream)
            : this(null, processInfoId, eventStream)
        {
            this.State = ActivityStateType.Started;
        }

        /// <summary>
        /// This method should ONLY be used when you are restarting a process to Update or End the activity
        /// </summary>
        /// <param name="processInfoId"></param>
        public ProcessTraceInfo(string processInfoId)
            : this(null, processInfoId)
        {
            this.State = ActivityStateType.Started;
        }

        #region ExceptionInfo Mgmt

        public override void AddException(Exception ex)
        {
            base.AddException(ex);
            this.ExceptionDetail.Begin(this);
        }

        #endregion

        #region AddDetail Mgmt
        public override LogDetail AddLogDetail()
        {
            var detailInfo = base.AddLogDetail();
            detailInfo.Begin(this);

            return detailInfo;
        }

        #endregion


        #region Set Individual Field Methods

        public void SetApplication(string applicationName)
        {
            this.UpdateActivity(PROCESSINFO_DATA_APPLICATION, applicationName);
        }

        public void SetUserName(string userName)
        {
            this.UpdateActivity(PROCESSINFO_DATA_USER_NAME, userName);
        }

        public void SetUserId(string userId)
        {
            this.UpdateActivity(PROCESSINFO_DATA_USER_ID, userId);
        }

        public void AddAssociatedProcess(string associatedProcessId)
        {
            this.EventStream.AddRelatedActivity(ActivityType.ProcessTraceInfo.ToString(), this.ProcessInfoId,
                                                            ActivityType.ProcessTraceInfo.ToString(), associatedProcessId);
        }

        #endregion


        #region Private Helpers
        
        internal override void TraceBeginEvent(string messageDataName, string messageData)
        {
            WorkflowProcessTraceSource.TraceEvent(TraceEventType.Information, ProcessDiagnosticsEventId.ProcessInfoStart,
                                    string.Format("Begin ProcessInfo Event.  ProcessInfoName: [{0}]", this.Name));

            WorkflowProcessTraceSource.TraceEvent(TraceEventType.Verbose, ProcessDiagnosticsEventId.ProcessInfoStart,
                            string.Format("Begin ProcessInfo Event.  ProcessInfoName: [{0}], " +
                                                "ProcessInputName: [{1}], ProcessInputData[{2}]",
                                                this.Name, messageDataName, messageData));
        }


        internal override void TraceEndEvent(bool successful, string messageDataName, string messageData)
        {
            WorkflowProcessTraceSource.TraceEvent(TraceEventType.Information, ProcessDiagnosticsEventId.ProcessInfoEnd,
                                    string.Format("End ProcessInfo Event.  ProcessInfoName: [{0}]",
                                    this.Name));

            WorkflowProcessTraceSource.TraceEvent(TraceEventType.Verbose, ProcessDiagnosticsEventId.ProcessInfoEnd,
                            string.Format("End ProcessInfo Event.  ProcessInfoName: [{0}], " +
                                                "ProcessOutputName: [{1}], ProcessOutputData: [{2}]",
                                                this.Name, messageDataName, messageData));
        }

        internal override void TraceUpdateActivity(string itemName, object itemValue)
        {
            WorkflowProcessTraceSource.TraceEvent(TraceEventType.Information, ProcessDiagnosticsEventId.ActivityUpdated,
                                    string.Format("ProcessInfo Update Activity.  ProcessInfo.{0} Value: [{1}]", itemName, itemValue));
        }
        #endregion

    }
}
